package fons.navigator.util.piccolo;

import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Paint;

import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.nodes.PText;
import edu.umd.cs.piccolo.util.PBounds;
import edu.umd.cs.piccolox.util.PFixedWidthStroke;


/**
 * @author Ilya Boyandin
 */
public class PLabel extends PNode {
	private static final long serialVersionUID = 1L;
	
	private static final Paint DEFAULT_LABEL_BG = Color.white; //*/ new Color(153, 153, 153);
	private Paint labelBackground = DEFAULT_LABEL_BG; // new Color(153, 153, 153);

	private static final Paint SEL_LABEL_BG = new Color(215, 48, 39);
	private Paint labelBackgroundSelected = SEL_LABEL_BG;

	private static final Color PRESSED_SEL_LABEL_BG = new Color(225, 58, 49);
	private static final Color NON_SEL_LABEL_FG = Color.black;
	private static final Color SEL_LABEL_FG = Color.white;
	private static final Color BORDER = new Color(100, 100, 100);
	private static final PFixedWidthStroke BORDER_STROKE = new PFixedWidthStroke(1.0f);

	private static final Font FONT = new Font("Arial", Font.PLAIN, 11);

	private final PText textNode;
	private final PPath rectNode;
	private final Insets pad;
	private final float arcWidth = 3;
	private final float arcHeight = 3;
	
	private boolean highlightOnMouseOver = true;

	public PLabel(String text) {
		this(text, new Insets(3, 3, 3, 3));
	}

	public PLabel(String text, Insets pad) {
		this.textNode = new PText(text);
		textNode.setFont(FONT);
		textNode.setPickable(false);
		this.pad = pad;
		PBounds textb = textNode.getFullBoundsReference();
		this.rectNode = PPath.createRoundRectangle(
				-pad.left, -pad.top, (float) textb.getWidth() + pad.left + pad.right,
				(float) textb.getHeight() + pad.top + pad.bottom, arcWidth, arcHeight
				);

		textNode.setTextPaint(NON_SEL_LABEL_FG);

		rectNode.setStroke(BORDER_STROKE);
		rectNode.setStrokePaint(BORDER);
		addChild(rectNode);
		addChild(textNode);
		onBoundsChanged();

		addInputEventListener(new PTypedBasicInputEventHandler<PLabel>(PLabel.class) {
			@Override
			public void mouseEntered(PInputEvent event) {
				if (highlightOnMouseOver) {
					PLabel label = node(event);
					label.getTextNode().setTextPaint(SEL_LABEL_FG);
					label.getRectNode().setPaint(labelBackgroundSelected);
					label.moveToFront();
					repaint();
				}
			}
			@Override
			public void mouseExited(PInputEvent event) {
				if (highlightOnMouseOver) {
					PLabel label = node(event);
					label.getTextNode().setTextPaint(NON_SEL_LABEL_FG);
					label.getRectNode().setPaint(labelBackground);
					repaint();
				}
			}
			@Override
			public void mousePressed(PInputEvent event) {
				PLabel label = node(event);
				label.getRectNode().setPaint(PRESSED_SEL_LABEL_BG);
				repaint();
			}
			@Override
			public void mouseReleased(PInputEvent event) {
				PLabel label = node(event);
				label.getRectNode().setPaint(SEL_LABEL_BG);
				repaint();
			}
		});
	}

	public void setLabelBackground(Paint labelBackground) {
		this.labelBackground = labelBackground;
		rectNode.setPaint(labelBackground);
	}

	@Override
	public boolean setBounds(double x, double y, double width, double height) {
		boolean rv = super.setBounds(x, y, width, height);
		if (rv) {
			onBoundsChanged();
		}
		return rv;
	}
	
	public void setHighlightOnMouseOver(boolean highlightOnMouseOver) {
		this.highlightOnMouseOver = highlightOnMouseOver;
	}

	public void highlight () {
		getTextNode().setTextPaint(SEL_LABEL_FG);
		getRectNode().setPaint(labelBackgroundSelected);
		moveToFront();
		repaint();
	}
	
	public void downlight () {
		getTextNode().setTextPaint(NON_SEL_LABEL_FG);
		getRectNode().setPaint(labelBackground);
		repaint();
	}
	
	@Override
	public void setPickable(boolean isPickable) {
		super.setPickable(isPickable);
		rectNode.setPickable(isPickable);
		textNode.setPickable(false);  // (otherwise it produces unnecessary mousein/out events)
	}

	private void onBoundsChanged() {
		textNode.setBounds(getBoundsReference());
		rectNode.setBounds(
				-pad.left + textNode.getX(),
				-pad.top + textNode.getY(),
				(float) textNode.getWidth() + pad.left + pad.right,
				(float) textNode.getHeight() + pad.top + pad.bottom);
	}

	public PText getTextNode() {
		return textNode;
	}

	public PPath getRectNode() {
		return rectNode;
	}

	public void setFont(Font font) {
		textNode.setFont(font);
		onBoundsChanged();
	}

	public Paint getLabelBackgroundSelected() {
		return labelBackgroundSelected;
	}

	public void setLabelBackgroundSelected(Paint labelBackgroundSelected) {
		this.labelBackgroundSelected = labelBackgroundSelected;
	}

}